package edu.ustb.mis.dm.impl.algorithm;

import java.util.ArrayList;
import java.util.List;
import edu.ustb.mis.dm.interfaces.algorithm.ClusterAlgorithm;
import edu.ustb.mis.dm.interfaces.data.DataOutput;
import edu.ustb.mis.dm.interfaces.data.DataPrepare;
import edu.ustb.mis.dm.model.WClusterResult;
import edu.ustb.mis.dm.model.unit.impl.Instance;

public abstract class AbstractWCABOSFV implements ClusterAlgorithm<WClusterResult> {
	protected DataPrepare<Instance> dataPrepare;

	protected DataOutput<WClusterResult> dataOutput;

	protected List<Instance> instanceList = new ArrayList<Instance>();

	protected List<WClusterResult> wClusterResultList;

	protected WClusterResult tmp_WClusterResult = new WClusterResult();

	protected double threshhold;

	protected float dissimilarity = 0;

	protected float tmp_dissimilarity = 100;

	protected int tmp_j = 1;

	protected WClusterResult wClusterResult;

	protected int category_count;

	protected Instance instance;

	/**
	 * 当差异度小于等于阈值的时候将元素加入现有类别
	 * 
	 * @param WClusterResultList
	 */
	protected void addToExist() {
		wClusterResult = wClusterResultList.get(tmp_j);
		wClusterResult.add(instance.getClassID(), instance.getAttributeSet(), tmp_dissimilarity);
	}

	/**
	 * 在差异度大于阈值的时候，新建类别并加入元素
	 * 
	 * @param WClusterResultList
	 * @param instanceList
	 * @param i
	 */
	protected void addToNew(final int i) {
		instance = instanceList.get(i);
		wClusterResultList.add(new WClusterResult(instance.getClassID(), instance.getAttributeSet()));
	}

	/**
	 * 计算两个元素间的差异度
	 * 
	 * @param j
	 */
	protected abstract float calculateDissimilarity(int j);

	/**
	 * CABOSFV聚类的主要方法
	 * 
	 * @param coefficient
	 * @param instanceList
	 * @return
	 */
	public List<WClusterResult> cluster() {
		final int instanceListSize = instanceList.size();
		instance = instanceList.get(0);
		wClusterResultList = new ArrayList<WClusterResult>();
		wClusterResultList.add(new WClusterResult(instance.getClassID(), instance.getAttributeSet()));
		boolean flag;
		for (int i = 1; i < instanceListSize; i++) {
			flag = true;
			instance = instanceList.get(i);
			category_count = wClusterResultList.size();
			for (int j = 0; j < category_count; j++) {
				dissimilarity = calculateDissimilarity(j);// 计算差异度
				if (dissimilarity <= threshhold) {
					tmp_j = j;
					tmp_dissimilarity = dissimilarity;
					this.addToExist();
					flag = false;
				}
			}
			if (flag) {
				this.addToNew(i);
			}
		}
		return wClusterResultList;
	}

	public List<Instance> getInstanceList() {
		return instanceList;
	}

	public List<WClusterResult> getResultList() {
		return wClusterResultList;
	}

	public void setDataOutput(final DataOutput<WClusterResult> dataOutput) {
		this.dataOutput = dataOutput;
	}

	public void setThreshhold(final double threshhold) {
		this.threshhold = threshhold;
	}
}
